package nancal.mp.config.base;

import feign.FeignException
import nancal.mp.config.errorResponseJson
import nbcp.base.comm.JsonResult
import nbcp.base.extend.AsString
import nbcp.base.extend.Slice
import nbcp.base.extend.toByteArray
import nbcp.base.extend.toUtf8String
import org.slf4j.LoggerFactory
import org.springframework.http.server.reactive.ServerHttpRequest
import org.springframework.http.server.reactive.ServerHttpResponse
import org.springframework.web.bind.annotation.ControllerAdvice
import org.springframework.web.bind.annotation.ExceptionHandler
import org.springframework.web.bind.annotation.ResponseBody
import reactor.core.publisher.Mono
import javax.crypto.BadPaddingException
import kotlin.jvm.optionals.getOrNull

@ControllerAdvice
@ResponseBody
class GlobalProcExp {
    companion object {
        private val logger = LoggerFactory.getLogger(this::class.java.declaringClass)
    }

    @ExceptionHandler(Exception::class)
    fun exp(ex: Exception, request: ServerHttpRequest, response: ServerHttpResponse): Mono<Void> {
        logger.error(ex.message, ex);

        if (response.statusCode.value() == 401) {
            return Mono.empty();
        }

        var error = ex.cause ?: ex;

        if (error is FeignException) {
            response.setRawStatusCode(error.status())
            return response.errorResponseJson(
                JsonResult.error(
                    "Feign: " + (error.responseBody()
                        .orElse(null)?.toByteArray()?.toUtf8String()
                        .AsString(error.message.AsString())).Slice(0, 1024),
                    0 - error.status()
                )
            )
        }

        return response.errorResponseJson(getExceptionSafeMessage(error))
    }

    private fun getExceptionSafeMessage(error: Throwable): JsonResult {
        if (error is BadPaddingException) {
            return JsonResult.error("RSA解密错误", -1)
        }

        return JsonResult.error(error.message.AsString(error::class.java.simpleName), -1)
    }
}
